package server;

import java.io.IOException;
import java.io.InputStream;

/**
 * Listener thread for the commands sent to the server
 */
public class ReadCommands extends Thread {

	private InputStream is;
	
	private int command;
	private Monitor monitor;
	private final int sizeOfInt = Integer.SIZE / Byte.SIZE; // Size of int in bytes
	

	/**
	 * Listener thread for the commands sent to the server
	 * @param is The input stream whence the commands come from
	 * @param monitor The monitor for the shared data in the server
	 */
	public ReadCommands(InputStream is, Monitor monitor) {
		command = Server.IDLE_COMMAND;
		this.is = is;
		this.monitor = monitor;
	}

	/**
	 * Helper command that does the actual fetching of the commands.
	 * Reads from the input stream.
	 * Stores the command to the monitor.
	 * @throws IOException if the stream botches
	 */
	private synchronized void fetchCommand() throws IOException {
		byte headerData[] = new byte[2*sizeOfInt];

		int size = 0;
		int header = 0;
		while (size == 0) {
			header = 0;
			while(header != 2*sizeOfInt){
				header += is.read(headerData, header, 2*sizeOfInt - header);
			}
			command = byteArrayToInt(headerData, 0);
			size = byteArrayToInt(headerData, sizeOfInt);
		}
		
		byte data[] = new byte[size];		
		int bytesRead = 0;
		while(bytesRead != size){
			bytesRead += is.read(data, bytesRead, size - bytesRead);			
		}
		
		String dataString = new String(data);
		
		monitor.setCommand(command, dataString);
	}
	
	/**
	 * Helper method to extract header information
	 * @param b byte[] to extract from
	 * @param offset offset in b
	 * @return
	 */
	private final int byteArrayToInt(byte[] b, int offset) {
		return (b[0 + offset] << 24) + ((b[1 + offset] & 0xFF) << 16)
				+ ((b[2 + offset] & 0xFF) << 8) + (b[3 + offset] & 0xFF);
	}

	/**
	 * Fetches new commands via {@link #fetchCommand()}
	 * until the monitor signals that the thread should be killed.
	 */
	public void run() {
		while (!monitor.threadKilled()) {
			try {
				fetchCommand();
			} catch (IOException e) {
				System.out.println("IOException in ReadCommands, client probably disconnected");
				return;
			}
		}
		return;
	}



}
